package com.bolt.support.spring.jpa.jpql;

import com.bolt.support.query.conditions.domain.SqlClause;

import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

public class Templates {

    private final static Map<Ops,String> templates = new IdentityHashMap<>();
    private final static Map<Ops,Integer> placeholderNum = new IdentityHashMap<>();


    public Templates() {
        templates.put(Ops.PROPERTY,"{0}.{1}");
        templates.put(Ops.ALIAS," as {0}");
        templates.put(Ops.ENTITY,"{0} {1}");
        templates.put(Ops.EQ,"{0}= {1}");

        templates.put(Ops.EQ,"{0} = {1}");
        templates.put(Ops.NE,"{0} != {1}");

        templates.put(Ops.GE,"{0} >= {1}");
        templates.put(Ops.GT,"{0} > {1}");
        templates.put(Ops.LE,"{0} <= {1}");
        templates.put(Ops.LT,"{0} < {1}");

        templates.put(Ops.AND," and ");
        templates.put(Ops.OR," or ");

        templates.put(Ops.LIKE,"{0} like {1}");
        templates.put(Ops.LIKERIGHT,"{0} like {1}");
        templates.put(Ops.LIKELEFT,"{0} like {1}");
        templates.put(Ops.BETWEEN,"{0} between {1} and {2}");
        templates.put(Ops.NOTBETWEEN,"{0} not between {1} and {2}");


        templates.put(Ops.IN,"{0} in ({1})");

        templates.put(Ops.NOTIN,"{0}  not in ({1})");

        templates.put(Ops.ISNULL,"{0} is null");
        templates.put(Ops.NOTNULL,"{0} is not null");

        templates.put(Ops.CONTAINS,"instr( {0}, {1}) > 0");

        templates.put(Ops.CONCAT, "concat({0},{1})");
        templates.put(Ops.GROUP_CONCAT, "group_concat({0})");
        templates.put(Ops.WM_CONCAT, "wm_concat({0})");
        templates.put(Ops.LOWER, "lower({0})");
        templates.put(Ops.SUBSTR, "substring({0},{1},{2})");
        templates.put(Ops.TRIM, "trim({0})");
        templates.put(Ops.UPPER, "upper({0})");
        templates.put(Ops.TOCHAR, "to_char({0})");



        templates.put(Ops.LOWER, "lower({0})");
        templates.put(Ops.SUBSTR, "substring({0},{1},{2})");
        templates.put(Ops.TRIM, "trim({0})");
        templates.put(Ops.UPPER, "upper({0})");

        templates.put(Ops.DIV, "div({0})");
        templates.put(Ops.SUB, "sub({0})");
        templates.put(Ops.MOD, "mod({0})");
        templates.put(Ops.AVG, "avg({0})");
        templates.put(Ops.SUM, "sum({0})");

        templates.put(Ops.MAX, "max({0})");
        templates.put(Ops.MIN, "min({0})");
        templates.put(Ops.COUNT, "count({0})");

        placeholderNum.put(Ops.AND,2);
        placeholderNum.put(Ops.OR,2);
        placeholderNum.put(Ops.OR,2);
        placeholderNum.put(Ops.BETWEEN,3);
        placeholderNum.put(Ops.NOTBETWEEN,3);

    }

    public String get(Ops ops){
        return templates.get(ops);
    }

    public List<? extends SqlClause<?>> convert(Ops operator , List <? extends SqlClause <?>> clauses){
       boolean isArg = clauses.stream().allMatch(k->k instanceof  OperationClause);
       if(isArg){
           return clauses;
       }
        Integer num = placeholderNum.get(operator);
        if (null == num ){
            num =2;
        }
        if(clauses.size() <= num){
           return clauses;
        }
        List <SqlClause <?>> subItem = new ArrayList<>();
        for(int i = 0; i < num; i++){
            subItem.add(clauses.get(i));
        }
       return subItem;
    }
}

 